package cn.qingyun.gis.modules.enterprise.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.json.JSONObject;
import cn.qingyun.gis.modules.enterprise.util.anno.CSVField;
import com.csvreader.CsvReader;
import com.google.common.base.Charsets;
import com.google.common.collect.Lists;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Scanner;

@Slf4j
public class CsvTool {
    private CsvTool() {
        throw new IllegalStateException("Utility class");
    }

    @SneakyThrows
    public static <T, R> List<R> transferFile(MultipartFile file, Class<T> fClass, Class<R> tClass) {
        CsvReader csvReader = new CsvReader(file.getInputStream(), StandardCharsets.UTF_8);
        // 读表头
        csvReader.setSafetySwitch(false);
        csvReader.readHeaders();

        List<T> imports = Lists.newArrayList();
        // 读内容
        while (csvReader.readRecord()) {
            imports.add(CsvTool.toBean(csvReader, fClass));
        }

        List<R> records = Lists.newArrayList();
        if (CollUtil.isNotEmpty(imports)) {
            for (T anImport : imports) {
                R district = tClass.newInstance();

                BeanUtils.copyProperties(anImport, district);
                records.add(district);
            }
        }

        return records;
    }

    @SneakyThrows
    public static <T> List<T> transferFile(MultipartFile file, Class<T> fClass) {
        CsvReader csvReader = new CsvReader(file.getInputStream(), StandardCharsets.UTF_8);
        // 读表头
        csvReader.setSafetySwitch(false);
        csvReader.readHeaders();

        List<T> imports = Lists.newArrayList();
        // 读内容
        while (csvReader.readRecord()) {
            imports.add(CsvTool.toBean(csvReader, fClass));
        }

        return imports;
    }

    @SneakyThrows
    public static <T> List<T> transferFile(File file, Class<T> fClass) {
        //预处理， 替换双引号
        String content = IoUtil.readUtf8(FileUtil.getInputStream(file));
        content = content.replaceAll("\uFEFF", "");

        CsvReader csvReader = new CsvReader(IoUtil.toUtf8Stream(content), Charsets.UTF_8);
        // 读表头
        csvReader.setSafetySwitch(false);
        csvReader.readHeaders();

        List<T> imports = Lists.newArrayList();
        // 读内容
        while (csvReader.readRecord()) {
            imports.add(CsvTool.toBean(csvReader, fClass));
        }

        return imports;
    }

    @SneakyThrows
    public static <T> T toBean(CsvReader csvReader, Class<T> tClass) {
        JSONObject jsonObject = new JSONObject();
        for (Field field : tClass.getDeclaredFields()) {
            CSVField annotation = field.getAnnotation(CSVField.class);
            if (Objects.nonNull(annotation)) {
                String key = annotation.value();
                jsonObject.set(field.getName(), csvReader.get(key));
            }
        }

        return jsonObject.toBean(tClass);
    }

    /**
     * 对原csv文件进行表头追加
     */
    @SneakyThrows
    public static void addHead(File file, String header) {
        try (RandomAccessFile raf = new RandomAccessFile(file, "rw");
             ByteArrayOutputStream baos = new ByteArrayOutputStream()) {

            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = raf.read(buffer)) != -1) {
                baos.write(buffer, 0, bytesRead);
            }

            raf.seek(0);
            raf.write((header + System.lineSeparator()).getBytes(StandardCharsets.UTF_8));
            raf.write(baos.toByteArray());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 对原csv文件中的分隔符（制表符 -> 逗号）
     */
    @SneakyThrows
    public static void transferTab(File file) {
        String originalDelimiter = "\t";
        String convertedDelimiter = ",";
        String quote = "\"";
        try {
            // 创建输入文件的Scanner对象
            Scanner scanner = new Scanner(file);

            // 创建StringBuilder对象来存储转换后的数据
            StringBuilder convertedData = new StringBuilder();

            // 逐行读取CSV文件
            while (scanner.hasNextLine()) {
                String line = scanner.nextLine();

                // 使用split()方法将每行数据按照分隔符拆分成单列元素
                String[] columns = line.split(originalDelimiter);

                // 遍历每个单列元素，并在其前后添加引号
                for (String column : columns) {
                    convertedData.append(quote).append(column).append(quote).append(convertedDelimiter);
                }

                // 删除最后一个多余的分隔符
                convertedData.deleteCharAt(convertedData.length() - 1);
                convertedData.append("\n");
            }

            // 关闭原文件
            scanner.close();

            // 使用FileWriter类将StringBuilder对象中的数据写入原文件
            FileWriter writer = new FileWriter(file);
            writer.write(convertedData.toString());

            // 关闭FileWriter
            writer.close();
            log.info("csv文件分隔符转换完成");

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @description: 字段值添加双引号
     * @author skb
     * @date 2024/1/5 14:52
     */
    @SneakyThrows
    public static void addDraw(File file) {
        String originalDelimiter = ",";
        String quote = "\"";
        try {
            // 创建输入文件的Scanner对象
            Scanner scanner = new Scanner(file);

            // 创建StringBuilder对象来存储转换后的数据
            StringBuilder convertedData = new StringBuilder();

            // 逐行读取CSV文件
            while (scanner.hasNextLine()) {
                String line = scanner.nextLine();

                // 使用split()方法将每行数据按照分隔符拆分成单列元素
                String[] columns = line.split(originalDelimiter);

                // 遍历每个单列元素，并在其前后添加引号
                for (String column : columns) {
                    convertedData.append(quote).append(column).append(quote).append(originalDelimiter);
                }

                // 删除最后一个多余的分隔符
                convertedData.deleteCharAt(convertedData.length() - 1);
                convertedData.append("\n");
            }

            // 关闭原文件
            scanner.close();

            // 使用FileWriter类将StringBuilder对象中的数据写入原文件
            FileWriter writer = new FileWriter(file);
            writer.write(convertedData.toString());

            // 关闭FileWriter
            writer.close();
            log.info("csv文件添加双引号完成");

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @description: 使用反射获取类的所有属性，并将每个属性的值添加到一个 String[] 数组中
     * @author skb
     * @date 2024/3/15 11:04
     */
    public static String[] getArrayFromObject(Object object) {
        Field[] fields = object.getClass().getDeclaredFields();
        String[] objArray = new String[fields.length];
        try {
            for (int i = 0; i < fields.length; i++) {
                Field field = fields[i];
                field.setAccessible(true);
                if (field.getType() == Date.class) {
                    objArray[i] = DateUtil.format((Date) field.get(object), "yyyy-MM-dd HH:mm:ss");
                } else {
                    objArray[i] = Objects.isNull(field.get(object)) ? null : String.valueOf(field.get(object));
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return objArray;
    }

}
